void loadInitialContext()
{
	int TheScheduler = slotOf( SchedulerAssociation, 2 );
	int activeProcess = slotOf( TheScheduler, 2 );
	int context = slotOf( activeProcess, 2 );
	
	loadContextRegistersFrom( context );
}

unsigned int reverse(unsigned int x)
{
	unsigned int a = (x>>24) & 0xFF;
	unsigned int b = (x>>16) & 0xFF;
	unsigned int c = (x>>8) & 0xFF;
	unsigned int d = (x>>0) & 0xFF;
	
	return (d<<24)|(c<<16)|(b<<8)|(a<<0);
}

#ifdef KERNEL
void drawTheScreen()
{
	//		int width, height, depth;
	//	  int address;
	//	  int scanLineSize;
	//} videoInfo;
	
	printf("%p\n",  video_info.address);
	printf("%d\n",  video_info.scanLineSize);
	//PANIC("");
	
	int screen = slotOf(specialObjectsArray, 48);
	
	int bits = slotOf(screen, 1);
	
	int formWidth = unpackSmInt(slotOf(screen, 2));
	
	int width = unpackSmInt(slotOf(screen, 2));
	int height = unpackSmInt(slotOf(screen, 3));
	int depth = unpackSmInt(slotOf(screen, 4));
	
	if( width > video_info.width) width = video_info.width;
	if( height > video_info.height) height = video_info.height;
	
	int src = bits + 4; //past the header
	int dst = video_info.address;
	
	for(int line=0; line<height; line++)
	{
		unsigned int* dstp = (unsigned int*)dst;
		unsigned int* srcp = (unsigned int*)src;
		
		for(int px=0; px< width; px++)
		{
			*dstp = *srcp;
			dstp++;
			srcp++;
		}
		
		src += (formWidth * 4);
		
		dst += (video_info.scanLineSize);
	}
}
#endif

void interpreterMain(void* heapAddr, int heapLength)
{
	loadImage(heapAddr, heapLength);
	loadInitialContext();
	
	recycleContext = nil;
	
	#ifdef KERNEL
	//drawTheScreen();
	#endif
	
	for(;;) //The bytecode loop
	{	
		unsigned char b = *pc++;
#ifdef PRINT_BYTECODES
		printcode(b); 
#endif

		unsigned char b2, b3, lobits;
		int i;
		switch(b)
		{
			// load receiver variable
			case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: 
            case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: 
                push( slotOf(rcvr, (b&0xF)+1) ); break;
			// load temporary variable
			case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: 
            case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: 
                push( slotOf(homeContext, Context_tempFrameStart+(b&0xF)+1) ); break;
			// loadLiteral
			case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: 
            case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: 
            case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: 
            case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: 
                push( slotOf(method, (b&0x1F)+2) ); break;
			// loadLiteralIndirect
			case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71: 
            case 72: case 73: case 74: case 75: case 76: case 77: case 78: case 79: 
            case 80: case 81: case 82: case 83: case 84: case 85: case 86: case 87: 
            case 88: case 89: case 90: case 91: case 92: case 93: case 94: case 95: 
                push( slotOf( slotOf(method, (b&0x1F)+2), 2 ) ); break;
			// storeAndPop rcvr, temp
            case 96: case 97: case 98: case 99: case 100: case 101: case 102: case 103: 
				setSlotOf( rcvr, (b&7)+1, pop() ); break;	
            case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111: 
				setSlotOf(homeContext, Context_tempFrameStart+1+(b&7), pop()); break;
			case 112: push(rcvr); break;
			case 113: push(true); break;
			case 114: push(false); break;
			case 115: push(nil); break;
			case 116: push(packSmInt(-1)); break;
			case 117: push(packSmInt(0)); break;
			case 118: push(packSmInt(1)); break;
			case 119: push(packSmInt(2)); break;
			case 120: doReturn( rcvr, slotOf(homeContext, 1) ); break;
			case 121: doReturn( true, slotOf(homeContext, 1) ); break;
			case 122: doReturn( false, slotOf(homeContext, 1) ); break;
			case 123: doReturn( nil, slotOf(homeContext, 1) ); break;
			case 124: doReturn( pop(), slotOf(homeContext, 1) ); break;
			case 125: doReturn( pop(), slotOf(activeContext, 1) ); break;
			case 126: 
				//PANIC("Unimplemented bytecode: dynamic super send");
				b2 = *pc++; //argc
				b3 = *pc++; //selector
				send( /*selector*/ slotOf( method, b3+2 ), /*arg count*/ b2, 2 /*dyanmic super*/);
				break;	
			case 127: 
				//PANIC("Unimplemented bytecode: push implicit receiver");
				b2 = *pc++;
				push(  implicitReceiver(rcvr, method, slotOf( method, b2+2 )) ); //1 for header, 1 for 1-origin
				break;
				
			case 128: //extendedPush
				b2 = *pc++; //next byte
				lobits= b2&63;
				switch (b2>>6) {
					case 0: push( slotOf(rcvr, lobits+1) ); break;
		            case 1: push( slotOf(homeContext, Context_tempFrameStart+lobits+1) ); break;
					case 2: push( slotOf(method, lobits+2) ); break;
					case 3: push( slotOf( slotOf(method, lobits+2) , Assn_value+1 ) ); break;
				}
				break;
            case 129: //extended store
				b2 = *pc++; //next byte
				lobits= b2&63;
				switch (b2>>6) {
					case 0: setSlotOf(rcvr, lobits+1, top()); break;
					case 1: setSlotOf( homeContext, Context_tempFrameStart+lobits+1, top() ); break;
					case 2: PANIC("!"); break;
					case 3: setSlotOf( slotOf(method, lobits+2), Assn_value+1, top() ); break;
				}
				break;
            case 130: //extendedStorePop
				b2 = *pc++; //next byte
				lobits= b2&63;
				switch (b2>>6) {
					case 0: setSlotOf(rcvr, lobits+1, pop()); break;
					case 1: setSlotOf( homeContext, Context_tempFrameStart+lobits+1, pop() ); break;
					case 2: PANIC("!"); break;
					case 3: setSlotOf( slotOf(method, lobits+2), Assn_value+1, pop() ); break;
				}
				break;
			case 131:
				b2 = *pc++;
				send( slotOf(method,(b2&31)+2), b2>>5, 0);
				break;
			case 132:
				b2 = *pc++;
				b3 = *pc++; 
		        switch (b2>>5) {
		            case 0: send( slotOf(method,b3+2), b2&31, 0); break;
		            case 1: send( slotOf(method,b3+2), b2&31, 1); break;
		            case 2: push( slotOf(rcvr,b3+1) ); break;
		            case 3: push( slotOf(method,b3+2) ); break;
		            case 4: push( slotOf( slotOf(method,b3+2) , 1) ); break;
		            case 5: setSlotOf(rcvr,b3+1,top()); break;
		            case 6: setSlotOf(rcvr,b3+1,pop()); break;
		            case 7: setSlotOf( slotOf(method,b3+2) , 1, top() ); break;
		        }
				break;
            case 133: // singleExtendedSendToSuper
				b2 = *pc++;
				send( slotOf(method,(b2&31)+2), b2>>5, 1);
				break;
            case 134: // secondExtendedSend 
				b2 = *pc++;
				send( slotOf(method,(b2&63)+2), b2>>6, 0);
				break;     
			case 135: pop(); break;	
            case 136: push(top()); break;
            case 137: push(activeContext); recyclableDepth=0; break;	
			case 138: case 139: case 140: case 141: case 142: case 143: PANIC("unused bytecode");
			case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: 
                pc+= (b&7)+1; break;
			case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159:
				i = pop();
				if(i==false) pc += (b&7)+1;
				else if(i==true) {}
				else {
					saveContextRegisters();
					printFullObject(activeContext);
					PANIC("non boolean!"); //proper response is to push i back then send ifFalse or something
				}
				break;
			// Long jump, forward and back
            case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: 
                b2 = *pc++;
                pc += (((b&7)-4)*256 + b2);
                if ((b&7)<4) checkForInterrupts();  //check on backward jumps (loops)
                break;
			// Long btp
            case 168: case 169: case 170: case 171:
				b2 = *pc++;
				i = pop();
				if(i==true) pc += ((b&3)*256 + b2);
				else if(i==false) {}
				else PANIC("non boolean !"); //should actually send #mustBeBoolean
				break;
            // Long bfp
            case 172: case 173: case 174: case 175: 
				b2 = *pc++;
				i = pop();
				if(i==true) {} 
				else if(i==false) pc += ((b&3)*256 + b2);
				else PANIC("non boolean !"); //should actually send #mustBeBoolean
				break;
			case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: 
			case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191:
				sendSpecial( b & 0xF ); break;
			case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: 
            case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: 
                sendSpecial((b&0xF)+16); break;				
			case 208: case 209: case 210: case 211: case 212: case 213:	case 214: case 215:
			case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223:
				send( /*selector*/ slotOf( method, (b&0xF)+2), /*arg count*/ 0, 0 ); break;
			case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231:
			case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239:
				send( /*selector*/ slotOf( method, (b&0xF)+2), /*arg count*/ 1, 0); break;
            case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: 
            case 248: case 249: case 250: case 251: case 252: case 253: case 254: case 255:
				send( /*selector*/ slotOf( method, (b&0xF)+2), /*arg count*/ 2, 0); break;	
			default:
				PANIC("Unknown bytecode");
		}
	}
}

